/*
 * smart-doc https://github.com/shalousun/smart-doc
 *
 * Copyright (C) 2018-2021 smart-doc
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package com.power.doc.builder;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.power.common.util.CollectionUtil;
import com.power.common.util.FileUtil;
import com.power.common.util.StringUtil;
import com.power.common.util.UUIDUtil;
import com.power.doc.constants.DocGlobalConstants;
import com.power.doc.factory.BuildTemplateFactory;
import com.power.doc.model.*;
import com.power.doc.model.postman.*;
import com.power.doc.model.postman.request.ParamBean;
import com.power.doc.model.postman.request.RequestBean;
import com.power.doc.model.postman.request.body.BodyBean;
import com.power.doc.model.postman.request.header.HeaderBean;
import com.power.doc.model.request.ApiRequestExample;
import com.power.doc.template.IDocBuildTemplate;
import com.power.doc.utils.DocPathUtil;
import com.power.doc.utils.JsonUtil;
import com.thoughtworks.qdox.JavaProjectBuilder;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import java.util.stream.Collectors;


/**
 * @author yu 2019/11/21.
 */
public class PostmanJsonBuilder {

    private static final String MSG = "Interface name is not set.";

    /**
     * build postman json
     *
     * @param config Smart-doc ApiConfig
     */
    public static void buildPostmanCollection(ApiConfig config) {
        DocBuilderTemplate builderTemplate = new DocBuilderTemplate();
        builderTemplate.checkAndInit(config);
        JavaProjectBuilder javaProjectBuilder = new JavaProjectBuilder();
        ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
        postManCreate(config, configBuilder);
    }

    /**
     * Only for smart-doc maven plugin and gradle plugin.
     *
     * @param config         ApiConfig Object
     * @param projectBuilder QDOX avaProjectBuilder
     */
    public static void buildPostmanCollection(ApiConfig config, JavaProjectBuilder projectBuilder) {
        DocBuilderTemplate builderTemplate = new DocBuilderTemplate();
        builderTemplate.checkAndInit(config);
        config.setParamsDataToTree(false);
        ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, projectBuilder);
        postManCreate(config, configBuilder);
    }

    /**
     * Build the first layer of Postman Item
     *
     * @param apiDoc Documentation for each Controller
     * @return First layer of Postman Item
     */
    private static ItemBean buildItemBean(ApiConfig config, ApiDoc apiDoc) {
        ItemBean itemBean = new ItemBean();
        itemBean.setName(StringUtil.isEmpty(apiDoc.getDesc()) ? MSG : apiDoc.getDesc());
        List<ItemBean> itemBeans = new ArrayList<>();
        List<ApiMethodDoc> apiMethodDocs = apiDoc.getList();
        apiMethodDocs.forEach(
                apiMethodDoc -> {
                    List<ItemBean> itemBean1 = buildItemV2(config, apiMethodDoc);
                    itemBeans.addAll(itemBean1);
                }
        );
        itemBean.setItem(itemBeans);
        return itemBean;
    }

    /**
     * Build the second layer of Postman item
     *
     * @param apiMethodDoc Documentation for each method
     * @return The second layer of Postman item
     */
    private static ItemBean buildItem(ApiMethodDoc apiMethodDoc) {
        ItemBean item = new ItemBean();
        RequestBean requestBean = new RequestBean();

        item.setName(StringUtil.isEmpty(apiMethodDoc.getDesc()) ? MSG : apiMethodDoc.getDesc());
        item.setDescription(apiMethodDoc.getDetail());

        requestBean.setDescription(apiMethodDoc.getDesc());
        requestBean.setMethod(apiMethodDoc.getType());
        requestBean.setHeader(buildHeaderBeanList(apiMethodDoc));

        requestBean.setBody(buildBodyBean(apiMethodDoc));
        requestBean.setUrl(buildUrlBean(apiMethodDoc));

        item.setRequest(requestBean);
        return item;

    }

    /**
     * Build the second layer of Postman item
     *
     * @param apiMethodDoc Documentation for each method
     * @return The second layer of Postman item
     */
    private static List<ItemBean> buildItemV2(ApiConfig config, ApiMethodDoc apiMethodDoc) {
        boolean xmErrorFlag = config.isXmErrorFlag();
        List<ItemBean> itemBeans = new ArrayList<>();

        boolean download = apiMethodDoc.isDownload();
        List<ApiParam> pathParams = apiMethodDoc.getPathParams();
        if (CollUtil.isNotEmpty(pathParams)) {
            // 修复
            if ((apiMethodDoc.getType().equals("GET") || apiMethodDoc.getType().equals("DELETE"))
                    && StrUtil.isNotBlank(apiMethodDoc.getName()) && apiMethodDoc.getName().contains("ById")) {
                ApiParam apiParam = pathParams.get(0);
                apiParam.setValue(Convert.toStr(RandomUtil.randomInt(1000000, 9000000)));
            }
        }
        if (xmErrorFlag) {
            pathParams = apiMethodDoc.getPathParams();
            if (CollUtil.isNotEmpty(pathParams)) {
                List<ApiParam> newPathParams = ObjectUtil.cloneByStream(apiMethodDoc.getPathParams());
                // 修复
                if ((apiMethodDoc.getType().equals("GET") || apiMethodDoc.getType().equals("DELETE"))
                        && StrUtil.isNotBlank(apiMethodDoc.getName()) && apiMethodDoc.getName().contains("ById")) {
                    ApiParam apiParam = newPathParams.get(0);
                    apiParam.setValue(RandomUtil.randomString(10));
                }

                ApiParam apiParam = newPathParams.get(0);
                String desc = StrUtil.trim(apiParam.getDesc());
                String apiMethodDocDesc =  StrUtil.trim(apiMethodDoc.getDesc());
                // 添加
                ApiMethodDoc newApiMethodDoc = new ApiMethodDoc();
                newApiMethodDoc.setMethodId(UUIDUtil.getUuid32());
                newApiMethodDoc.setDesc(apiMethodDocDesc + "-验证异常-输入字母查询");
                newApiMethodDoc.setPathParams(newPathParams);


                newApiMethodDoc.setRequestParams(apiMethodDoc.getRequestParams());
                newApiMethodDoc.setRequestExample(apiMethodDoc.getRequestExample());
                newApiMethodDoc.setName(apiMethodDoc.getName());
                newApiMethodDoc.setIsRequestArray(apiMethodDoc.getIsRequestArray());
                newApiMethodDoc.setRequestArrayType(apiMethodDoc.getRequestArrayType());
                newApiMethodDoc.setIsResponseArray(apiMethodDoc.getIsResponseArray());
                newApiMethodDoc.setResponseArrayType(apiMethodDoc.getResponseArrayType());
                newApiMethodDoc.setListParam(apiMethodDoc.isListParam());
                newApiMethodDoc.setUrl(apiMethodDoc.getUrl());
                newApiMethodDoc.setType(apiMethodDoc.getType());
                newApiMethodDoc.setResponseUsage(apiMethodDoc.getResponseUsage());
                newApiMethodDoc.setRequestUsage(apiMethodDoc.getRequestUsage());
                newApiMethodDoc.setContentType(apiMethodDoc.getContentType());
                newApiMethodDoc.setHeaders(apiMethodDoc.getHeaders());
                newApiMethodDoc.setOrder(apiMethodDoc.getOrder());
                newApiMethodDoc.setResponseParams(apiMethodDoc.getResponseParams());
                newApiMethodDoc.setRequestHeaders(apiMethodDoc.getRequestHeaders());
                newApiMethodDoc.setDetail(apiMethodDoc.getDetail());
                newApiMethodDoc.setAuthor(apiMethodDoc.getAuthor());
                newApiMethodDoc.setPath(apiMethodDoc.getPath());
                newApiMethodDoc.setServerUrl(apiMethodDoc.getServerUrl());
                newApiMethodDoc.setDeprecated(apiMethodDoc.isDeprecated());
                newApiMethodDoc.setQueryParams(apiMethodDoc.getQueryParams());
                newApiMethodDoc.setReturnSchema(apiMethodDoc.getReturnSchema());
                newApiMethodDoc.setRequestSchema(apiMethodDoc.getRequestSchema());
                newApiMethodDoc.setGroup(apiMethodDoc.getGroup());
                newApiMethodDoc.setDownload(apiMethodDoc.isDownload());
                newApiMethodDoc.setLink(apiMethodDoc.getLink());
                newApiMethodDoc.setPage(apiMethodDoc.getPage());
                newApiMethodDoc.setTags(apiMethodDoc.getTags());
                //apiMethodDocs.add(newApiMethodDoc);


                RequestBean requestBean = new RequestBean();
                ItemBean item = new ItemBean();
                item.setName(StringUtil.isEmpty(newApiMethodDoc.getDesc()) ? MSG : newApiMethodDoc.getDesc());
                item.setDescription(newApiMethodDoc.getDetail());

                requestBean.setDescription(newApiMethodDoc.getDesc());
                requestBean.setMethod(newApiMethodDoc.getType());
                requestBean.setHeader(buildHeaderBeanList(newApiMethodDoc));

                requestBean.setBody(buildBodyBean(newApiMethodDoc));
                requestBean.setUrl(buildUrlBean(newApiMethodDoc));

                if (download) {
                    EventBean event = getDownloadEventBean();
                    item.setEvent(Collections.singletonList(event));
                } else {
                    EventBean event = getNotNumberEventBean(desc);
                    item.setEvent(Collections.singletonList(event));
                }

                item.setRequest(requestBean);
                itemBeans.add(item);
            }

            List<ApiParam> queryParams = apiMethodDoc.getQueryParams();
            if (queryParams != null && !queryParams.isEmpty()) {

                RequestBean requestBean = new RequestBean();
                ItemBean item = new ItemBean();
                item.setName(StringUtil.isEmpty(apiMethodDoc.getDesc()) ? MSG : apiMethodDoc.getDesc());
                item.setDescription(apiMethodDoc.getDetail());

                requestBean.setDescription(apiMethodDoc.getDesc());
                requestBean.setMethod(apiMethodDoc.getType());
                requestBean.setHeader(buildHeaderBeanList(apiMethodDoc));

                requestBean.setBody(buildBodyBean(apiMethodDoc));
                requestBean.setUrl(buildUrlBean(apiMethodDoc));

                EventBean event = getNormalEventBean(apiMethodDoc);
                if (event != null) {
                    item.setEvent(Collections.singletonList(event));
                }

                item.setRequest(requestBean);
                itemBeans.add(item);
            }


            List<ApiParam> requestParams = apiMethodDoc.getRequestParams();
            if (requestParams != null && !requestParams.isEmpty()) {
                ApiRequestExample requestExample = apiMethodDoc.getRequestExample();
                String jsonBody = requestExample.getJsonBody();
                for (ApiParam apiParam : requestParams) {
                    String field = apiParam.getField();
                    String desc = StrUtil.trim(apiParam.getDesc());
                    String maxLength = apiParam.getMaxLength();
                    boolean required = apiParam.isRequired();
                    if (required) {
                        ApiMethodDoc newApiMethodDoc = new ApiMethodDoc();
                        newApiMethodDoc.setMethodId(UUIDUtil.getUuid32());
                        newApiMethodDoc.setDesc(StrUtil.trim(apiMethodDoc.getDesc()) + "-验证异常-" + desc + "字段不传");
                        List<ApiParam> apiParamList = apiMethodDoc.getRequestParams();
                        List<ApiParam> newApiParamList = new ArrayList<>();
                        for (ApiParam param : apiParamList) {
                            if (param.getField().equals(field)) {
                                continue;
                            }
                            newApiParamList.add(param);
                        }
                        newApiMethodDoc.setRequestParams(newApiParamList);
                        newApiMethodDoc.setRequestExample(ObjectUtil.cloneByStream(requestExample));
                        JSONObject jsonObject = JSONUtil.parseObj(jsonBody);
                        jsonObject.remove(field);
                        newApiMethodDoc.getRequestExample().setJsonBody(jsonObject.toStringPretty());

                        newApiMethodDoc.setName(apiMethodDoc.getName());
                        newApiMethodDoc.setIsRequestArray(apiMethodDoc.getIsRequestArray());
                        newApiMethodDoc.setRequestArrayType(apiMethodDoc.getRequestArrayType());
                        newApiMethodDoc.setIsResponseArray(apiMethodDoc.getIsResponseArray());
                        newApiMethodDoc.setResponseArrayType(apiMethodDoc.getResponseArrayType());
                        newApiMethodDoc.setListParam(apiMethodDoc.isListParam());
                        newApiMethodDoc.setUrl(apiMethodDoc.getUrl());
                        newApiMethodDoc.setType(apiMethodDoc.getType());
                        newApiMethodDoc.setResponseUsage(apiMethodDoc.getResponseUsage());
                        newApiMethodDoc.setRequestUsage(apiMethodDoc.getRequestUsage());
                        newApiMethodDoc.setContentType(apiMethodDoc.getContentType());
                        newApiMethodDoc.setHeaders(apiMethodDoc.getHeaders());
                        newApiMethodDoc.setOrder(apiMethodDoc.getOrder());
                        newApiMethodDoc.setResponseParams(apiMethodDoc.getResponseParams());
                        newApiMethodDoc.setRequestHeaders(apiMethodDoc.getRequestHeaders());
                        newApiMethodDoc.setDetail(apiMethodDoc.getDetail());
                        newApiMethodDoc.setAuthor(apiMethodDoc.getAuthor());
                        newApiMethodDoc.setPath(apiMethodDoc.getPath());
                        newApiMethodDoc.setServerUrl(apiMethodDoc.getServerUrl());
                        newApiMethodDoc.setDeprecated(apiMethodDoc.isDeprecated());
                        newApiMethodDoc.setPathParams(apiMethodDoc.getPathParams());
                        newApiMethodDoc.setQueryParams(apiMethodDoc.getQueryParams());
                        newApiMethodDoc.setReturnSchema(apiMethodDoc.getReturnSchema());
                        newApiMethodDoc.setRequestSchema(apiMethodDoc.getRequestSchema());
                        newApiMethodDoc.setGroup(apiMethodDoc.getGroup());
                        newApiMethodDoc.setDownload(apiMethodDoc.isDownload());
                        newApiMethodDoc.setLink(apiMethodDoc.getLink());
                        newApiMethodDoc.setPage(apiMethodDoc.getPage());
                        newApiMethodDoc.setTags(apiMethodDoc.getTags());
                        //apiMethodDocs.add(newApiMethodDoc);


                        RequestBean requestBean = new RequestBean();
                        ItemBean item = new ItemBean();
                        item.setName(StringUtil.isEmpty(newApiMethodDoc.getDesc()) ? MSG : newApiMethodDoc.getDesc());
                        item.setDescription(newApiMethodDoc.getDetail());

                        requestBean.setDescription(newApiMethodDoc.getDesc());
                        requestBean.setMethod(newApiMethodDoc.getType());
                        requestBean.setHeader(buildHeaderBeanList(newApiMethodDoc));

                        requestBean.setBody(buildBodyBean(newApiMethodDoc));
                        requestBean.setUrl(buildUrlBean(newApiMethodDoc));

                        EventBean event = getNotExistsFieldEventBean(desc);
                        item.setEvent(Collections.singletonList(event));

                        item.setRequest(requestBean);
                        itemBeans.add(item);
                    }
                    if (maxLength != null && !maxLength.isEmpty()) {
                        long len = Long.parseLong(maxLength);
                        if (len > 0) {
                            ApiMethodDoc newApiMethodDoc = new ApiMethodDoc();
                            newApiMethodDoc.setMethodId(UUIDUtil.getUuid32());
                            newApiMethodDoc.setDesc(StrUtil.trim(apiMethodDoc.getDesc()) + "-验证异常-" + desc + "长度超过限制");
                            newApiMethodDoc.setRequestParams(ObjectUtil.cloneByStream(apiMethodDoc.getRequestParams()));
                            for (ApiParam param : newApiMethodDoc.getRequestParams()) {
                                if (param.getType().equals("string")) {
                                    if (param.getField().equals(field)) {
                                        String value = param.getValue();
                                        param.setValue(StrUtil.fillAfter(value, 'a', (int) (len + 10)));
                                    }
                                } else if (param.getType().equals("array")) {
                                    String value = param.getValue();
                                    List<String> split = StrUtil.split(value, ",");
                                    if (CollUtil.isNotEmpty(split)) {
                                        String newValue = split.stream()
                                                .map(a -> StrUtil.fillAfter(a, 'a', (int) (len + 10)))
                                                .collect(Collectors.joining(","));
                                        param.setValue(newValue);
                                    }
                                }
                            }
                            JSONObject jsonObject = JSONUtil.parseObj(jsonBody);
                            Object o = jsonObject.get(field);
                            if (o instanceof JSONArray) {
                                JSONArray jsonArray = jsonObject.getJSONArray(field);
                                List<String> newList = new ArrayList<>();
                                for (Object o1 : jsonArray) {
                                    if (o1 instanceof String) {
                                        String newValue = StrUtil.fillAfter((String) o1, 'a', (int) (len + 10));
                                        newList.add(newValue);
                                    }
                                }
                                if (CollUtil.isNotEmpty(newList)) {
                                    jsonArray.clear();
                                    jsonArray.addAll(newList);
                                }
                            } else if (o instanceof JSONObject) {
                                JSONObject objJson = jsonObject.getJSONObject(field);
                            } else if (o instanceof String) {
                                String value = jsonObject.getStr(field);
                                String newValue = StrUtil.fillAfter(value, 'a', (int) (len + 10));
                                jsonObject.set(field, newValue);
                            }

                            newApiMethodDoc.setRequestExample(ObjectUtil.cloneByStream(requestExample));
                            newApiMethodDoc.getRequestExample().setJsonBody(jsonObject.toStringPretty());

                            newApiMethodDoc.setIsRequestArray(apiMethodDoc.getIsRequestArray());
                            newApiMethodDoc.setRequestArrayType(apiMethodDoc.getRequestArrayType());
                            newApiMethodDoc.setIsResponseArray(apiMethodDoc.getIsResponseArray());
                            newApiMethodDoc.setResponseArrayType(apiMethodDoc.getResponseArrayType());
                            newApiMethodDoc.setListParam(apiMethodDoc.isListParam());
                            newApiMethodDoc.setName(apiMethodDoc.getName());
                            newApiMethodDoc.setUrl(apiMethodDoc.getUrl());
                            newApiMethodDoc.setType(apiMethodDoc.getType());
                            newApiMethodDoc.setResponseUsage(apiMethodDoc.getResponseUsage());
                            newApiMethodDoc.setRequestUsage(apiMethodDoc.getRequestUsage());
                            newApiMethodDoc.setContentType(apiMethodDoc.getContentType());
                            newApiMethodDoc.setHeaders(apiMethodDoc.getHeaders());
                            newApiMethodDoc.setOrder(apiMethodDoc.getOrder());
                            newApiMethodDoc.setResponseParams(apiMethodDoc.getResponseParams());
                            newApiMethodDoc.setRequestHeaders(apiMethodDoc.getRequestHeaders());
                            newApiMethodDoc.setDetail(apiMethodDoc.getDetail());
                            newApiMethodDoc.setAuthor(apiMethodDoc.getAuthor());
                            newApiMethodDoc.setPath(apiMethodDoc.getPath());
                            newApiMethodDoc.setServerUrl(apiMethodDoc.getServerUrl());
                            newApiMethodDoc.setDeprecated(apiMethodDoc.isDeprecated());
                            newApiMethodDoc.setPathParams(apiMethodDoc.getPathParams());
                            newApiMethodDoc.setQueryParams(apiMethodDoc.getQueryParams());
                            newApiMethodDoc.setReturnSchema(apiMethodDoc.getReturnSchema());
                            newApiMethodDoc.setRequestSchema(apiMethodDoc.getRequestSchema());
                            newApiMethodDoc.setGroup(apiMethodDoc.getGroup());
                            newApiMethodDoc.setDownload(apiMethodDoc.isDownload());
                            newApiMethodDoc.setLink(apiMethodDoc.getLink());
                            newApiMethodDoc.setPage(apiMethodDoc.getPage());
                            newApiMethodDoc.setTags(apiMethodDoc.getTags());
                            //apiMethodDocs.add(newApiMethodDoc);

                            ItemBean item = new ItemBean();
                            item.setName(StringUtil.isEmpty(newApiMethodDoc.getDesc()) ? MSG : newApiMethodDoc.getDesc());
                            item.setDescription(newApiMethodDoc.getDetail());

                            RequestBean requestBean = new RequestBean();
                            requestBean.setDescription(newApiMethodDoc.getDesc());
                            requestBean.setMethod(newApiMethodDoc.getType());
                            requestBean.setHeader(buildHeaderBeanList(newApiMethodDoc));

                            requestBean.setBody(buildBodyBean(newApiMethodDoc));
                            requestBean.setUrl(buildUrlBean(newApiMethodDoc));

                            EventBean event = getLenExceedLimitEventBean(apiParam.getMaxLengthErrorStr());
                            item.setEvent(Collections.singletonList(event));

                            item.setRequest(requestBean);
                            itemBeans.add(item);
                        }
                    }
                }


             /*   RequestBean requestBean = new RequestBean();
                ItemBean item = new ItemBean();
                item.setName(StringUtil.isEmpty(apiMethodDoc.getDesc()) ? MSG : apiMethodDoc.getDesc());
                item.setDescription(apiMethodDoc.getDetail());

                requestBean.setDescription(apiMethodDoc.getDesc());
                requestBean.setMethod(apiMethodDoc.getType());
                requestBean.setHeader(buildHeaderBeanList(apiMethodDoc));

                requestBean.setBody(buildBodyBean(apiMethodDoc));
                requestBean.setUrl(buildUrlBean(apiMethodDoc));
*//*
            EventBean event = getNormalEventBean();
            item.setEvent(event);*//*

                item.setRequest(requestBean);
                if (itemBeans.stream().noneMatch(a -> a.getName().equals(item.getName()))) {
                    itemBeans.add(item);
                }*/
            }/* else {

                RequestBean requestBean = new RequestBean();
                ItemBean item = new ItemBean();
                item.setName(StringUtil.isEmpty(apiMethodDoc.getDesc()) ? MSG : apiMethodDoc.getDesc());
                item.setDescription(apiMethodDoc.getDetail());

                requestBean.setDescription(apiMethodDoc.getDesc());
                requestBean.setMethod(apiMethodDoc.getType());
                requestBean.setHeader(buildHeaderBeanList(apiMethodDoc));

                requestBean.setBody(buildBodyBean(apiMethodDoc));
                requestBean.setUrl(buildUrlBean(apiMethodDoc));

                item.setRequest(requestBean);

                if (itemBeans.stream().noneMatch(a -> a.getName().equals(item.getName()))) {
                    itemBeans.add(item);
                }
            }*/
        } else {
            RequestBean requestBean = new RequestBean();
            ItemBean item = new ItemBean();
            item.setName(StringUtil.isEmpty(apiMethodDoc.getDesc()) ? MSG : apiMethodDoc.getDesc());
            item.setDescription(apiMethodDoc.getDetail());

            requestBean.setDescription(StrUtil.trim(apiMethodDoc.getDesc()));
            requestBean.setMethod(apiMethodDoc.getType());
            requestBean.setHeader(buildHeaderBeanList(apiMethodDoc));

            requestBean.setBody(buildBodyBean(apiMethodDoc));
            requestBean.setUrl(buildUrlBean(apiMethodDoc));

            item.setRequest(requestBean);
            itemBeans.add(item);
        }
        return itemBeans;

    }

    private static EventBean getDownloadEventBean() {

        EventBean event = new EventBean();
        event.setListen("test");
        ScriptBean script = new ScriptBean();
        event.setScript(script);
        script.setId(IdUtil.randomUUID());
        script.setType("text/javascript");
        script.setExec(new String[]{
                "pm.test(\"验证状态码 200\", function () {",
                "    pm.response.to.have.status(200);",
                "});",
                "",
                "var json = pm.response.json();",
                "pm.test(\"验证返回值结构\", function () {",
                "    pm.expect(json).to.have.all.keys(\"code\", \"msg\", \"data\");",
                "    pm.expect(json.code).to.eql(1);",
                "    pm.expect(json.msg).to.include(\"文件读取异常\");",
                "    pm.expect(json.data).to.eql(null);",
                "});",
        });
        return event;
    }

    private static EventBean getNotNumberEventBean(String desc) {

        EventBean event = new EventBean();
        event.setListen("test");
        ScriptBean script = new ScriptBean();
        event.setScript(script);
        script.setId(IdUtil.randomUUID());
        script.setType("text/javascript");
        script.setExec(new String[]{
                "pm.test(\"验证状态码 400\", function () {",
                "    pm.response.to.have.status(400);",
                "});",
                "",
                "var json = pm.response.json();",
                "pm.test(\"验证返回值结构\", function () {",
                "    pm.expect(json).to.have.all.keys(\"code\", \"msg\", \"data\");",
                "    pm.expect(json.code).to.eql(400);",
                "    pm.expect(json.msg).to.eql(\"" + desc + "长度超过限制而且只能是正整数\");",
                "    pm.expect(json.data).to.eql(null);",
                "});",
        });
        return event;
    }

    private static EventBean getLenExceedLimitEventBean(String maxLengthErrorStr) {

        EventBean event = new EventBean();
        event.setListen("test");
        ScriptBean script = new ScriptBean();
        event.setScript(script);
        script.setId(IdUtil.randomUUID());
        script.setType("text/javascript");
        script.setExec(new String[]{
                "pm.test(\"验证状态码 400\", function () {",
                "    pm.response.to.have.status(400);",
                "});",
                "",
                "var json = pm.response.json();",
                "pm.test(\"验证返回值结构\", function () {",
                "    pm.expect(json).to.have.all.keys(\"code\", \"msg\", \"data\");",
                "    pm.expect(json.code).to.eql(400);",
                "    pm.expect(json.msg).to.eql(" + maxLengthErrorStr + ");",
                "    pm.expect(json.data).to.eql(null);",
                "});",
        });
        return event;
    }

    private static EventBean getNotExistsFieldEventBean(String desc) {
        EventBean event = new EventBean();
        event.setListen("test");
        ScriptBean script = new ScriptBean();
        event.setScript(script);
        script.setId(IdUtil.randomUUID());
        script.setType("text/javascript");
        script.setExec(new String[]{
                "pm.test(\"验证状态码 400\", function () {",
                "    pm.response.to.have.status(400);",
                "});",
                "",
                "var json = pm.response.json();",
                "pm.test(\"验证返回值结构\", function () {",
                "    pm.expect(json).to.have.all.keys(\"code\", \"msg\", \"data\");",
                "    pm.expect(json.code).to.eql(400);",
                "    pm.expect(json.msg).to.eql(\"" + desc + "不能为空\");",
                "    pm.expect(json.data).to.eql(null);",
                "});"
        });
        return event;
    }


    private static EventBean getNormalEventBean(ApiMethodDoc apiMethodDoc) {
        EventBean event = new EventBean();
        event.setListen("test");
        ScriptBean script = new ScriptBean();
        event.setScript(script);
        script.setId(IdUtil.randomUUID());
        script.setType("text/javascript");
        JSONObject responseJsonObject = null;
        try {
            responseJsonObject = JSONUtil.parseObj(apiMethodDoc.getResponseUsage());
        } catch (Exception e) {
            System.out.println("不处理JSON数组: " + apiMethodDoc.getResponseUsage());
            return null;
        }
        Object data = responseJsonObject.get("data");
        String checkData = "    pm.expect(json.data).to.be.an('object');";
        String result = "        pm.expect(data).to.have.all.keys({},\"pages\");";
        String result2 = "    pm.expect(data.{}).to.have.all.keys({});";
        String checkRresult = "";
        if (data instanceof JSONObject) {
            Set<String> keys = ((JSONObject) data).keySet();
            String collect = keys.stream()
                    .map(a -> "\"" + a + "\"")
                    .collect(Collectors.joining(","));
            result = StrUtil.format(result, collect);
            // 处理分页查询
            if (((JSONObject) data).containsKey("records")) {
                Set<Map.Entry<String, Object>> dataEntrys = ((JSONObject) data).entrySet();
                for (Map.Entry<String, Object> dataEntry : dataEntrys) {
                    String dataKey = dataEntry.getKey();
                    Object dataValue = dataEntry.getValue();
                    if (dataValue instanceof JSONArray) {
                        Object o = ((JSONArray) dataValue).get(0);
                        if (o instanceof JSONObject) {
                            collect = ((JSONObject) o).keySet().stream()
                                    .map(a -> "\"" + a + "\"")
                                    .collect(Collectors.joining(","));
                            result2 = StrUtil.format(result2, dataKey, collect);

                            Set<Map.Entry<String, Object>> fields = ((JSONObject) o).entrySet();
                            for (Map.Entry<String, Object> field : fields) {
                                String fieldKey = field.getKey();
                                Object fieldValue = field.getValue();
                                if (fieldValue instanceof JSONObject) {
                                    String temp = StrUtil.format("//    pm.expect(data.{}.{}).to.an('object');@", dataKey, fieldKey);
                                    checkRresult += temp;
                                } else if (fieldValue instanceof JSONArray) {
                                    String temp = StrUtil.format("//    pm.expect(data.{}.{}).to.an('array');@", dataKey, fieldKey);
                                    checkRresult += temp;
                                } else {
                                    String temp = StrUtil.format("//    pm.expect(data.{}.{}).to.eql(\"\");@", dataKey, fieldKey);
                                    checkRresult += temp;
                                }
                            }
                        }
                    }
                }
            } else {
                Set<Map.Entry<String, Object>> entries = ((JSONObject) data).entrySet();
                for (Map.Entry<String, Object> entry : entries) {
                    String key = entry.getKey();
                    Object value = entry.getValue();
                    if (value instanceof JSONObject) {
                        String temp = StrUtil.format("//    pm.expect(data.{}).to.an('object');@", key);
                        checkRresult += temp;
                    } else if (value instanceof JSONArray) {
                        String temp = StrUtil.format("//    pm.expect(data.{}).to.an('array');@", key);
                        checkRresult += temp;
                    } else {
                        String temp = StrUtil.format("//    pm.expect(data.{}).to.eql(\"\");@", key);
                        checkRresult += temp;
                    }
                }
            }
        } else if (data instanceof JSONArray) {
            checkData = "    pm.expect(json.data).to.be.an(\"array\");";
            result = "";
        }

        List<String> stringList = new ArrayList<>();
        stringList.add("pm.test(\"验证状态码\", function () {");
        stringList.add("    pm.response.to.have.status(200);");
        stringList.add("});");
        stringList.add("");
        stringList.add("");
        stringList.add("var json = pm.response.json();");
        stringList.add("pm.test(\"验证返回值结构\", function () {");
        stringList.add("    pm.expect(json).to.have.all.keys(\"code\", \"msg\", \"data\")");
        stringList.add("    pm.expect(json.code).to.eql(0);");
        stringList.add("    pm.expect(json.msg).to.eql(null);");
        stringList.add(checkData);
        stringList.add("});");
        stringList.add("");
        stringList.add("var data = json.data");
        stringList.add("pm.test(\"验证业务返回值结构\", function () {");
        stringList.add(result);
        stringList.add("//    " + result2 + "");
        stringList.add("});");
        stringList.add("");
        stringList.add("");
        stringList.add("pm.test(\"验证业务返回值\", function () {");
        if (StrUtil.isNotBlank(checkRresult)) {
            String[] split = checkRresult.split("@");
            for (String s : split) {
                stringList.add(s);
            }
        }
        stringList.add("});");

        String[] exec = stringList.toArray(new String[]{});
        script.setExec(exec);
        return event;
    }

    private static UrlBean buildUrlBean(ApiMethodDoc apiMethodDoc) {
        UrlBean urlBean = new UrlBean();
        String url = Optional.ofNullable(apiMethodDoc.getRequestExample().getUrl()).orElse(apiMethodDoc.getUrl());
        urlBean.setRaw(DocPathUtil.toPostmanPath(url));
        try {
            URL javaUrl = new java.net.URL(apiMethodDoc.getServerUrl());
            if (javaUrl.getPort() == -1) {
                urlBean.setPort(null);
            } else {
                urlBean.setPort(String.valueOf(javaUrl.getPort()));
            }
            // set protocol
            String protocol = javaUrl.getProtocol();
            if (StringUtil.isNotEmpty(protocol)) {
                urlBean.setProtocol(protocol);
            }

            List<String> hosts = new ArrayList<>();
            hosts.add(javaUrl.getHost());
            urlBean.setHost(hosts);

            List<String> paths = new ArrayList<>();
            paths.add(javaUrl.getPath());
            urlBean.setPath(paths);
        } catch (MalformedURLException e) {
        }
        String shortUrl = DocPathUtil.toPostmanPath(apiMethodDoc.getPath());
        String[] paths = shortUrl.split("/");
        List<String> pathList = new ArrayList<>();
        String serverPath = urlBean.getPath().get(0);
        // Add server path
        if (CollectionUtil.isNotEmpty(urlBean.getPath()) && !shortUrl.contains(serverPath)) {
            String[] serverPaths = serverPath.split("/");
            pathList.addAll(Arrays.asList(serverPaths));
        }
        // Add mapping path
        for (String str : paths) {
            if (StringUtil.isNotEmpty(str)) {
                pathList.add(str);
            }
        }
        if (shortUrl.endsWith("/")) {
            pathList.add("");
        }

        urlBean.setPath(pathList);
        List<ParamBean> queryParams = new ArrayList<>();
        for (ApiParam apiParam : apiMethodDoc.getQueryParams()) {
            ParamBean queryParam = new ParamBean();
            queryParam.setDescription(StrUtil.trim(apiParam.getDesc()));
            queryParam.setKey(apiParam.getField());
            queryParam.setValue(apiParam.getValue());
            queryParams.add(queryParam);
        }
        List<ParamBean> variables = new ArrayList<>();
        for (ApiParam apiParam : apiMethodDoc.getPathParams()) {
            ParamBean queryParam = new ParamBean();
            queryParam.setDescription(StrUtil.trim(apiParam.getDesc()));
            queryParam.setKey(apiParam.getField());
            queryParam.setValue(apiParam.getValue());
            variables.add(queryParam);
        }
        urlBean.setVariable(variables);
        urlBean.setQuery(queryParams);
        return urlBean;
    }

    /**
     * Build payload
     *
     * @return Body payload
     */
    private static BodyBean buildBodyBean(ApiMethodDoc apiMethodDoc) {
        BodyBean bodyBean;
        if (apiMethodDoc.getContentType().contains(DocGlobalConstants.JSON_CONTENT_TYPE)) {
            bodyBean = new BodyBean(Boolean.FALSE);// Json request
            bodyBean.setMode(DocGlobalConstants.POSTMAN_MODE_RAW);
            if (apiMethodDoc.getRequestExample() != null) {
                bodyBean.setRaw(apiMethodDoc.getRequestExample().getJsonBody());
            }
        } else {
            bodyBean = new BodyBean(Boolean.TRUE); //Formdata
            bodyBean.setMode(DocGlobalConstants.POSTMAN_MODE_FORMDATA);
            bodyBean.setFormdata(apiMethodDoc.getRequestExample().getFormDataList());
        }
        return bodyBean;

    }

    /**
     * Build header
     *
     * @return List of header
     */
    private static List<HeaderBean> buildHeaderBeanList(ApiMethodDoc apiMethodDoc) {
        List<HeaderBean> headerBeans = new ArrayList<>();
        List<ApiReqParam> headers = apiMethodDoc.getRequestHeaders();
        headers.forEach(
                apiReqHeader -> {
                    HeaderBean headerBean = new HeaderBean();
                    headerBean.setKey(apiReqHeader.getName());
                    headerBean.setName(apiReqHeader.getName());
                    headerBean.setValue(apiReqHeader.getValue());
                    headerBean.setDisabled(!apiReqHeader.isRequired());
                    headerBean.setDescription(StrUtil.trim(apiReqHeader.getDesc()));
                    headerBeans.add(headerBean);
                }
        );

        if (apiMethodDoc.getContentType().contains(DocGlobalConstants.JSON_CONTENT_TYPE)) {
            HeaderBean headerBean = new HeaderBean();
            headerBean.setKey("Content-Type");
            headerBean.setName("Content-Type");
            headerBean.setValue("application/json");
            headerBean.setDisabled(false);
            headerBean.setType("text");
            headerBeans.add(headerBean);
        }
        return headerBeans;
    }

    private static void postManCreate(ApiConfig config, ProjectDocConfigBuilder configBuilder) {
        IDocBuildTemplate docBuildTemplate = BuildTemplateFactory.getDocBuildTemplate(config.getFramework());
        List<ApiDoc> apiDocList = docBuildTemplate.getApiData(configBuilder);
        RequestItem requestItem = new RequestItem();
        requestItem.setInfo(new InfoBean(config.getProjectName()));
        List<ItemBean> itemBeans = new ArrayList<>();
        apiDocList.forEach(
                apiDoc -> {
                    ItemBean itemBean = buildItemBean(config, apiDoc);
                    itemBeans.add(itemBean);
                }
        );
        requestItem.setItem(itemBeans);
        AuthBean auth = new AuthBean();
        requestItem.setAuth(auth);
        auth.setType("bearer");

        BearerBean bearerBean = new BearerBean();
        auth.setBearer(Collections.singletonList(bearerBean));
        bearerBean.setKey("token");
        bearerBean.setValue("{{access_token}}");
        bearerBean.setType("string");

        requestItem.setEvent(new EventBean[]{
                buildPrerequestEvent(),
                buildTestEvent(),
        });

        String filePath = config.getOutPath();
        filePath = filePath + DocGlobalConstants.POSTMAN_JSON;
        String data = JsonUtil.toPrettyJson(requestItem);
        FileUtil.nioWriteFile(data, filePath);
    }


    private static EventBean buildPrerequestEvent() {
        EventBean temp = new EventBean();
        temp.setListen("prerequest");
        ScriptBean script = new ScriptBean();
        temp.setScript(script);
        script.setId(IdUtil.randomUUID());
        script.setType("text/javascript");
        script.setExec(new String[]{"var auth = pm.request.headers.get(\"Authorization\");",
                "var tenantId = pm.request.headers.toObject(true)['tenant-id'];",
                "",
                "if (tenantId === null || !tenantId) {",
                "    tenantId = 1;",
                "}",
                "",
                "var oldToken = pm.globals.get('access_token');",
                "if (!oldToken) {",
                "    console.log(tenantId + \": 获取 token\");",
                "    // Example with a full-fledged request",
                "    const postRequest = {",
                "      url: 'http://edu:9999/auth/oauth/token?grant_type=password',",
                "      method: 'POST',",
                "      header: {",
                "        'Authorization':'Basic dGVzdDp0ZXN0',",
                "        'Accept-Language': 'zh-CN,zh',",
                "        'TENANT-ID':tenantId,",
                "        //'VERSION':'zyf'",
                "      },",
                "      body: {",
                "        mode: 'urlencoded',",
                "        urlencoded: [{ key:'username', value:'admin'},",
                "                {key:'password',value:'JFat0Zdc'},",
                "                {key:'scope',value:'server' }]",
                "      }",
                "    };",
                "    pm.sendRequest(postRequest, (error, response) => {",
                "      if (error) {",
                "        console.log(error);",
                "      } else {",
                "        console.log(response.json());",
                "        var token = response.json().access_token;",
                "        console.log(token);",
                "        pm.globals.set('access_token', token);",
                "      }",
                "    });",
                "}"});
        return temp;
    }

    private static EventBean buildTestEvent() {
        EventBean temp = new EventBean();
        temp.setListen("test");
        ScriptBean script = new ScriptBean();
        temp.setScript(script);
        script.setId(IdUtil.randomUUID());
        script.setType("text/javascript");
        script.setExec(new String[]{"",
                "",
                "pm.test(\"验证业务请求超时不超过 10s\", function () {",
                "    pm.expect(pm.response.responseTime).to.be.below(10000);",
                "});",
                "",
                "",
                "",
                "",
                "",
                "",
                "",
                "",
                "",
                "",
                "",
                "var auth = pm.request.headers.get(\"Authorization\");",
                "var tenantId = pm.request.headers.toObject(true)['tenant-id'];",
                "",
                "if (tenantId === null || !tenantId) {",
                "    tenantId = 1;",
                "}",
                "var jsonData = pm.response.json();",
                "if (!!jsonData && jsonData.msg == \"用户凭证已过期\") {",
                "    console.log(tenantId + \": 重新获取 token\");",
                "    ",
                "    // Example with a full-fledged request",
                "    const postRequest = {",
                "      url: 'http://edu:9999/auth/oauth/token?grant_type=password',",
                "      method: 'POST',",
                "      header: {",
                "        'Authorization':'Basic dGVzdDp0ZXN0',",
                "        'Accept-Language': 'zh-CN,zh',",
                "        'TENANT-ID':tenantId,",
                "        //'VERSION':'zyf'",
                "      },",
                "      body: {",
                "        mode: 'urlencoded',",
                "        urlencoded: [{ key:'username', value:'admin'},",
                "                {key:'password',value:'JFat0Zdc'},",
                "                {key:'scope',value:'server' }]",
                "      }",
                "    };",
                "    pm.sendRequest(postRequest, (error, response) => {",
                "      if (error) {",
                "        console.log(error);",
                "      } else {",
                "        console.log(response.json());",
                "        var token = response.json().access_token;",
                "        console.log(token);",
                "        pm.globals.set('access_token', token);",
                "      }",
                "    });",
                "}",
                ""});
        return temp;
    }

}
